#pragma once
#include "vector.h"

/**
 * Klasa plaszczyzny 3D
 *
 * @author Krzysztof Klein
 * @version 0.1
 */
class Plane
{

	/**
	 * Wektor normalny do plaszczyzny
	 */
	Vector n;

	/**
	 * Odleglosc plaszczyzny
	 */
	float d;

public:

	/**
	 * Konstruktor domyslny
	 */
	Plane() : n(0, 0, 0), d(0) { }

	/**
	 * Konstruktor z rownania ogolnego plaszczyzny
	 *
	 * @param a Wspolczynnik A
	 * @param b Wspolczynnik B
	 * @param c Wspolczynnik C
	 * @param d Wspolczynnik D
	 */
	Plane(float a, float b, float c, float d) : n(a, b, c), d(d) { n.normalize(); }

	/**
	 * Konstruktor z wektora normalnego i odleglosci plaszczyzny
	 *
	 * @param n Wektor normalny
	 * @param d Odleglosc plaszczyzny
	 */
	Plane(const Vector &n, float d) : n(n), d(d) { this->n.normalize(); }

	/**
	 * Konstruktor z wektora normalnego i punktu na plaszczyznie
	 *
	 * @param n Wektor normalny
	 * @param p Punkt na plaszczyznie
	 */
	Plane(const Vector &n, const Vector &p) : n(n) { d = -this->n.normalize().dotProduct(p); }

	/**
	 * Konstruktor z 3 punktow
	 *
	 * @param v1 Punkt 1
	 * @param v2 Punkt 2
	 * @param v3 Punkt 3
	 */
	Plane(const Vector &v1, const Vector &v2, const Vector &v3)	{ n = (v2 - v1).crossProduct(v3 - v1); d = -n.normalize().dotProduct(v1); }


	/**
	 * Wektor normalny do plaszczyzny
	 *
	 * @return Wektor normalny do plaszczyzny
	 */
	const Vector& getNormal() const { return n; }

	/**
	 * Wektor normalny do plaszczyzny
	 *
	 * @return Wektor normalny do plaszczyzny
	 */
	Vector& getNormal() { return n; }


	/**
	 * Odleglosc plaszczyzny
	 *
	 * @return Odleglosc plaszczyzny
	 */
	float getDistance() const { return d; }

	
	/**
	 * Iloczyn skalarny plaszczyzny z wektorem.
	 * Oblicza N dot V + d
	 *
	 * @param v Wektor
	 * @return Iloczyn skalarny
	 */
	float dotProduct(const Vector &v) const { return n.dotProduct(v) + d; }


	/**
	 * Sprawdza czy wektor kierunkowy wskazuje strone plaszczyzny
	 * ktora wskazuje wektor normalny.
	 *
	 * @param direction Wektor kierunkowy
	 * @return True jesli wskazuje. False jesli nie.
	 */
	bool isFrontFacing(const Vector &direction) const { return n.dotProduct(direction) <= 0; }

};
